// /** 
// * Descripttion:  Copyright (c) 2020 Sprocomm. All rights reserved.
// * version:  V1.0 
// * Author:  Sprocomm
// * Date: 2020-10-23 10:38:10
// * LastEditors:  Sprocomm
// * LastEditTime: 2020-10-26 09:59:40
// **/
// #include <iostream>

// using namespace std;

// #include <gtest/gtest.h>

// /**
//  * @file vptr1.cpp
//  * @brief C++虚函数vptr和vtable
//  * 编译：g++ -g -o vptr vptr1.cpp -std=c++11
//  * @author 光城
//  * @version v1
//  * @date 2019-07-20
//  */

// #include <iostream>
// #include <stdio.h>
// using namespace std;

// /**
//  * @brief 函数指针
//  */
// typedef void (*Fun)();

// /**
//  * @brief 基类
//  */
// class Base
// {
//     public:
//         Base(){};
//         virtual void fun1()
//         {
//             cout << "Base::fun1()" << endl;
//         }
//         virtual void fun2()
//         {
//             cout << "Base::fun2()" << endl;
//         }
//         virtual void fun3(){}
//         ~Base(){};
// };

// /**
//  * @brief 派生类
//  */
// class Derived: public Base
// {
//     public:
//         Derived(){};
//         void fun1()
//         {
//             cout << "Derived::fun1()" << endl;
//         }
//         void fun2()
//         {
//             cout << "DerivedClass::fun2()" << endl;
//         }
//         ~Derived(){};
// };
// /**
//  * @brief 获取vptr地址与func地址,vptr指向的是一块内存，这块内存存放的是虚函数地址，这块内存就是我们所说的虚表
//  *
//  * @param obj
//  * @param offset
//  *
//  * @return 
//  */
// Fun getAddr(void* obj,unsigned int offset)
// {
//     cout<<"======================="<<endl;
//     void* vptr_addr = (void *)*(unsigned long *)obj;  //64位操作系统，占8字节，通过*(unsigned long *)obj取出前8字节，即vptr指针
//     printf("vptr_addr:%p\n",vptr_addr);

//     /**
//      * @brief 通过vptr指针访问virtual table，因为虚表中每个元素(虚函数指针)在64位编译器下是8个字节，因此通过*(unsigned long *)vptr_addr取出前8字节，
//      * 后面加上偏移量就是每个函数的地址！
//      */
//     void* func_addr = (void *)*((unsigned long *)vptr_addr+offset);
//     printf("func_addr:%p\n",func_addr);
//     return (Fun)func_addr;
// }

// TEST(test_vptb, test1){

//     Base ptr;
//     Derived d;
//     Base *pt = new Derived();
//     Base &xx = ptr;
//     Base &pp = ptr;
//     Base &p = d;

//     ptr.fun1();

//     pp.fun1();

//     pt->fun1();
    
//     p.fun1();

//     // 手动查找vptr 和 vtable
//     Fun f1 = getAddr(pt, 0);
//     (*f1)();

//     // 虚函数地址相当于静态变量,保存在代码区.
//     Base *pt1 = new Derived();
//     Fun f2 = getAddr(pt1, 0);
//     (*f2)();
//     delete pt;
//     // return 0;
// }
